#include "uart_server.h"
#include "uart_interface.h"
#include "memory/memory.h"
#include "data_center/data_center.h"
#include "pico/mutex.h"
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "shell_cmd_list.h"
#include <string.h>
#include <stdlib.h>

#define LOG_TAG "UART_SERVER"
#include "log/log.h"


#define CALL_BACK_ARR_CAPACITY 4

static mutex_t lock_;  // 锁
static Bool    is_init_ = False;  // 是否已初始化
static UInt8   recv_buf_[128];  // 串口接收缓存
static UInt16  recv_data_len_ = 0;  // 串口接收数据长度


Bool TUartServerInit(void)
{
    uart_init(uart0, 115200);
    gpio_set_function(0, GPIO_FUNC_UART);
    gpio_set_function(1, GPIO_FUNC_UART);

    mutex_init(&lock_);
    TDataCenterInit(kDataCenterUserShell);
    is_init_ = True;

    return is_init_;
}

Bool TUartServerFini(void)
{
    if (is_init_)
    {
        TDataCenterFini(kDataCenterUserShell);
        is_init_ = False;
    }

    return is_init_ == False;
}

static void DoUartSend(const UInt8 *data, Int32 data_len)
{
    if (is_init_)
    {
        uart_write_blocking(uart0, data, data_len);
    }
}

static void DoUartRecv(UInt8 *data, Int32 data_len)
{
    if (is_init_)
    {
        TShellGetData(data, data_len);
    }
}

void TUartServerRunOnce(void)
{
    if (is_init_)
    {
        // 接收消息部分
        while (uart_is_readable(uart0) > 0)
        {
            Int8 ch = uart_getc(uart0);

            if (ch <= -1)
                continue;

            switch (ch)
            {
            case '\r':
                uart_putc(uart0, '\r');
                uart_putc(uart0, '\n');
                recv_buf_[recv_data_len_] = '\0';
                recv_data_len_ ++;
                DoUartRecv(recv_buf_, recv_data_len_);
                recv_data_len_ = 0;
                break;
            case '\n':  // 不接收，但回写
                uart_putc(uart0, ch);
                break;
            case '\b':  // 退格键
                if (recv_data_len_ > 0)
                {
                    uart_putc(uart0, '\b');
                    uart_putc(uart0, ' ');
                    uart_putc(uart0, '\b');
                    recv_data_len_ --;
                }
                break;

            default:
                uart_putc(uart0, ch);
                recv_buf_[recv_data_len_] = ch;
                recv_data_len_ ++;
                break;
            }
        }
    }
}

Int32 TUartSendData(const UInt8 *data, Int32 data_len)
{
    if (is_init_ && data != NULL && data_len > 0)
    {
        mutex_enter_blocking(&lock_);
        DoUartSend(data, data_len);
        mutex_exit(&lock_);
    }
}
